package hr.utils.Result;

import java.util.HashMap;
import java.util.Map;

import org.apache.poi.ss.formula.functions.T;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 泛型类，用于表示通用的响应对象。包含响应码、消息和数据。
 *
 * @author 柳继纪
 * @version 1.0.1
 * @since 1.0.0
 */
public class R {
    private static final Logger log = LoggerFactory.getLogger(R.class);

    /**
     * 响应码
     */
    private Integer code;

    /**
     * 响应消息
     */
    private String message;

    /**
     * 响应数据
     */
    private Object data;

    /**
     * 构造成功响应对象，包含响应数据。
     *
     * @param data 响应数据
     * @param <E>  数据的类型
     * @return 成功响应对象
     */
    public static <E> R success(E data) {
        if (checkDataType(data)) {
            log.warn("参数 {}，类型 {} 可能不符合 JSON 格式标准", data, data.getClass());
        }

        return builder().code(ResponseCodeMsg.SUCCESS.code).message(ResponseCodeMsg.SUCCESS.message).data(data).build();
    }

    /**
     * 构造成功响应对象，不包含响应数据。
     *
     * @return 成功响应对象
     */
    public static R success() {
        return builder().code(ResponseCodeMsg.SUCCESS.code).message(ResponseCodeMsg.SUCCESS.message).build();
    }

    /**
     * 构造错误响应对象，包含响应数据。
     *
     * @param data 响应数据
     * @param <E>  数据的类型
     * @return 错误响应对象
     */
    public static <E> R error(E data) {
        if (checkDataType(data)) {
            log.warn("参数 {}，类型 {} 可能不符合 JSON 格式标准", data, data.getClass());
        }

        return builder().code(ResponseCodeMsg.ERROR.code).message(ResponseCodeMsg.ERROR.message).data(data).build();
    }

    /**
     * 构造错误响应对象，不包含响应数据。
     *
     * @return 错误响应对象
     */
    public static R error() {
        return builder().code(ResponseCodeMsg.ERROR.code).message(ResponseCodeMsg.ERROR.message).build();
    }

    /**
     * 根据对象调用该方法像返回数据添加键值对数据
     * @param key
     * @param value
     * @return
     * @param <E>
     */
    public <E> R addKeyValueToData(String key, E value) {
        if (this.data == null) {
            this.data =  new HashMap<String, Object>();
        }
        Map<String, Object> data = (Map) this.data;
        data.put(key, value);
        return this;
    }

    /**
     * 构造自定义响应对象，包含自定义响应码和消息，但不包含数据。
     *
     * @param code    自定义响应码
     * @param message 自定义响应消息
     * @return 自定义响应对象
     */
    public static R buildCustomCodeAndMessage(Integer code, String message) {
        return builder().code(code).message(message).data(new HashMap<>()).build();
    }

    /**
     * 向当前响应对象的数据中添加自定义参数。
     *
     * @param key   参数的键
     * @param value 参数的值
     * @param <E>   参数值的类型
     * @param <V>   参数值的类型
     * @return 当前响应对象
     * @throws Exception 如果当前响应对象的数据类型不是Map，则抛出异常
     */
    public <E, V> R buildCustomData(E key, V value) throws Exception {
        if (!(this.data instanceof Map)) {
            throw new Exception(this.getClass() + " 只能向 Map 类型添加参数");
        } else {
            Map data = (Map) this.data;
            data.put(key, value);
            return this;
        }
    }

    /**
     * 检查数据类型，判断是否符合 JSON 格式标准。
     *
     * @param data 待检查的数据
     * @param <V>  数据的类型
     * @return 如果数据类型是基本数据类型（String、Integer、Byte、Character、Short、Long、Double、Float）则返回true，否则返回false。
     */
    private static <V> Boolean checkDataType(V data) {
        return !(!(data instanceof String) && !(data instanceof Integer) && !(data instanceof Byte) &&
                !(data instanceof Character) && !(data instanceof Short) && !(data instanceof Long) &&
                !(data instanceof Double) && !(data instanceof Float));
    }

    /**
     * 获取响应对象的构建器。
     *
     * @param <T> 构建器的泛型参数，与响应对象的泛型参数相同
     * @return 构建器对象
     */
    public static <T> RBuilder<T> builder() {
        return new RBuilder<>();
    }

    /**
     * 无参构造方法，用于创建无初始值的响应对象。
     */
    public R() {
    }

    /**
     * 构造方法，用于创建包含响应码、响应消息和响应数据的响应对象。
     *
     * @param code    响应码
     * @param message 响应消息
     * @param data    响应数据
     */
    public R(final Integer code, final String message, final Object data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    /**
     * 获取响应码。
     *
     * @return 响应码
     */
    public Integer getCode() {
        return this.code;
    }

    /**
     * 获取响应消息。
     *
     * @return 响应消息
     */
    public String getMessage() {
        return this.message;
    }

    /**
     * 获取响应数据。
     *
     * @return 响应数据
     */
    public Object getData() {
        return this.data;
    }

    /**
     * 设置响应码。
     *
     * @param code 新的响应码
     * @return 当前响应对象
     */
    public R setCode(final Integer code) {
        this.code = code;
        return this;
    }

    /**
     * 设置响应消息。
     *
     * @param message 新的响应消息
     * @return 当前响应对象
     */
    public R setMessage(final String message) {
        this.message = message;
        return this;
    }

    /**
     * 设置响应数据。
     *
     * @param data 新的响应数据
     * @return 当前响应对象
     */
    public R setData(final T data) {
        this.data = data;
        return this;
    }

    /**
     * 判断当前响应对象与另一对象是否相等。
     *
     * @param o 另一对象
     * @return 如果相等则返回true，否则返回false
     */
    public boolean equals(final Object o) {
        if (o == this) {
            return true;
        } else if (!(o instanceof R other)) {


            return false;
        } else {
            if (!other.canEqual(this)) {
                return false;
            } else {
                label47:
                {
                    Object this$code = this.getCode();
                    Object other$code = other.getCode();
                    if (this$code == null) {
                        if (other$code == null) {
                            break label47;
                        }
                    } else if (this$code.equals(other$code)) {
                        break label47;
                    }

                    return false;
                }

                Object this$message = this.getMessage();
                Object other$message = other.getMessage();
                if (this$message == null) {
                    if (other$message != null) {
                        return false;
                    }
                } else if (!this$message.equals(other$message)) {
                    return false;
                }

                Object this$data = this.getData();
                Object other$data = other.getData();
                if (this$data == null) {
                    if (other$data != null) {
                        return false;
                    }
                } else if (!this$data.equals(other$data)) {
                    return false;
                }

                return true;
            }
        }
    }

    /**
     * 判断当前响应对象是否可以与另一对象进行比较。
     *
     * @param other 另一对象
     * @return 如果可以比较则返回true，否则返回false
     */
    protected boolean canEqual(final Object other) {
        return other instanceof R;
    }

    /**
     * 计算当前响应对象的哈希值。
     *
     * @return 哈希值
     */
    public int hashCode() {
        boolean PRIME = true;
        int result = 1;
        Object $code = this.getCode();
        result = result * 59 + ($code == null ? 43 : $code.hashCode());
        Object $message = this.getMessage();
        result = result * 59 + ($message == null ? 43 : $message.hashCode());
        Object $data = this.getData();
        result = result * 59 + ($data == null ? 43 : $data.hashCode());
        return result;
    }

    /**
     * 将当前响应对象转换为字符串表示。
     *
     * @return 字符串表示
     */
    public String toString() {
        Integer var10000 = this.getCode();
        return "R(code=" + var10000 + ", message=" + this.getMessage() + ", data=" + this.getData() + ")";
    }

    /**
     * 构建响应对象的构建器。
     *
     * @param <T> 构建器的泛型参数，与响应对象的泛型参数相同
     */
    public static class RBuilder<T> {
        private Integer code;
        private String message;
        private T data;

        /**
         * 无参构造方法，用于创建响应对象的构建器。
         */
        RBuilder() {
        }

        /**
         * 设置响应码。
         *
         * @param code 新的响应码
         * @return 当前构建器对象
         */
        public RBuilder<T> code(final Integer code) {
            this.code = code;
            return this;
        }

        /**
         * 设置响应消息。
         *
         * @param message 新的响应消息
         * @return 当前构建器对象
         */
        public RBuilder<T> message(final String message) {
            this.message = message;
            return this;
        }

        /**
         * 设置响应数据。
         *
         * @param data 新的响应数据
         * @return 当前构建器对象
         */
        public RBuilder<T> data(final T data) {
            this.data = data;
            return this;
        }

        /**
         * 构建响应对象。
         *
         * @return 响应对象
         */
        public R build() {
            return new R(this.code, this.message, this.data);
        }

        /**
         * 将当前构建器对象转换为字符串表示。
         *
         * @return 字符串表示
         */
        public String toString() {
            return "R.RBuilder(code=" + this.code + ", message=" + this.message + ", data=" + this.data + ")";
        }
    }
}

/**
 * 表示响应代码和相应消息的枚举。
 * 此枚举中的每个常量都有一个关联的代码和消息。
 *
 * @author 柳继纪
 * @version 1.0.0
 * @since 1.0.0
 */
enum ResponseCodeMsg {

    /**
     * 表示一个成功的响应，代码为200，消息为“成功”。
     */
    SUCCESS(200, "成功"),

    /**
     * 表示错误响应，代码为500，消息为“错误”。
     */
    ERROR(500, "错误");

    /**
     * 与响应关联的数字代码。
     * 例如，200表示成功，500表示错误。
     */
    public final Integer code;

    /**
     * 与响应代码相关联的人类可读消息。
     * 这提供了有关响应的附加上下文或详细信息。
     */
    public final String message;

    /**
     * 使用指定的代码和消息构造一个新的ResponseCodeMsg常量。
     *
     * @param code    与响应关联的数字代码。
     * @param message 与响应代码相关联的人类可读消息。
     */
    ResponseCodeMsg(Integer code, String message) {
        this.code = code;
        this.message = message;
    }
}